#ifndef _WX_SCROLWIN_H_BASE_
#define _WX_SCROLWIN_H_BASE_

#include "wx/panel.h"

#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL)

class wxScrollHelperEvtHandler;
class wxTimer;


class wxScrollHelper {
  public:
    wxScrollHelper( wxWindow *winToScroll );
    virtual ~wxScrollHelper();
    virtual void SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY,
                                int noUnitsX, int noUnitsY,
                                int xPos = 0, int yPos = 0,
                                bool noRefresh = false );
    virtual void Scroll( int x, int y );
    int GetScrollPageSize( int orient ) const;
    void SetScrollPageSize( int orient, int pageSize );
    int GetScrollLines( int orient ) const;
    void SetScrollRate( int xstep, int ystep );
    virtual void GetScrollPixelsPerUnit( int *pixelsPerUnitX,
                                         int *pixelsPerUnitY ) const;
    virtual void EnableScrolling( bool x_scrolling, bool y_scrolling );
    virtual void GetViewStart( int *x, int *y ) const;
    void SetScale( double xs, double ys ) { m_scaleX = xs; m_scaleY = ys; }
    double GetScaleX() const { return m_scaleX; }
    double GetScaleY() const { return m_scaleY; }
    void CalcScrolledPosition( int x, int y, int *xx, int *yy ) const {
      DoCalcScrolledPosition( x, y, xx, yy );
    }
    wxPoint CalcScrolledPosition( const wxPoint& pt ) const {
      wxPoint p2;
      DoCalcScrolledPosition( pt.x, pt.y, &p2.x, &p2.y );
      return p2;
    }

    void CalcUnscrolledPosition( int x, int y, int *xx, int *yy ) const {
      DoCalcUnscrolledPosition( x, y, xx, yy );
    }
    wxPoint CalcUnscrolledPosition( const wxPoint& pt ) const {
      wxPoint p2;
      DoCalcUnscrolledPosition( pt.x, pt.y, &p2.x, &p2.y );
      return p2;
    }

    virtual void DoCalcScrolledPosition( int x, int y, int *xx, int *yy ) const;
    virtual void DoCalcUnscrolledPosition( int x, int y, int *xx, int *yy ) const;
    virtual void AdjustScrollbars( void );
    virtual int CalcScrollInc( wxScrollWinEvent& event );
    virtual void SetTargetWindow( wxWindow *target );
    virtual wxWindow *GetTargetWindow() const;
    void SetTargetRect( const wxRect& rect ) { m_rectToScroll = rect; }
    wxRect GetTargetRect() const { return m_rectToScroll; }
    virtual void OnDraw( wxDC& dc ) { }
    virtual void DoPrepareDC( wxDC& dc );
    bool IsAutoScrolling() const { return m_timerAutoScroll != NULL; }
    void StopAutoScrolling();
    virtual bool SendAutoScrollEvents( wxScrollWinEvent& event ) const;
    void HandleOnScroll( wxScrollWinEvent& event );
    void HandleOnSize( wxSizeEvent& event );
    void HandleOnPaint( wxPaintEvent& event );
    void HandleOnChar( wxKeyEvent& event );
    void HandleOnMouseEnter( wxMouseEvent& event );
    void HandleOnMouseLeave( wxMouseEvent& event );
    #if wxUSE_MOUSEWHEEL
    void HandleOnMouseWheel( wxMouseEvent& event );
    #endif

    void HandleOnChildFocus( wxChildFocusEvent& event );
    void OnScroll( wxScrollWinEvent& event ) { HandleOnScroll( event ); }

  protected:

    const wxRect *GetScrollRect() const {
      return m_rectToScroll.width != 0 ? &m_rectToScroll : NULL;
    }


    wxSize GetTargetSize() const {
      return m_rectToScroll.width != 0 ? m_rectToScroll.GetSize()
             : m_targetWindow->GetClientSize();
    }

    void GetTargetSize( int *w, int *h ) const {
      wxSize size = GetTargetSize();
      if( w ) {
        *w = size.x;
      }
      if( h ) {
        *h = size.y;
      }
    }

    bool ScrollLayout();
    void ScrollDoSetVirtualSize( int x, int y );
    wxSize ScrollGetBestVirtualSize() const;
    wxSize ScrollGetWindowSizeForVirtualSize( const wxSize& size ) const;
    void DoSetTargetWindow( wxWindow *target );
    void DeleteEvtHandler();
    double                m_scaleX;
    double                m_scaleY;
    wxWindow             *m_win,
                         *m_targetWindow;
    wxRect                m_rectToScroll;
    wxTimer              *m_timerAutoScroll;
    int                   m_xScrollPixelsPerLine;
    int                   m_yScrollPixelsPerLine;
    int                   m_xScrollPosition;
    int                   m_yScrollPosition;
    int                   m_xScrollLines;
    int                   m_yScrollLines;
    int                   m_xScrollLinesPerPage;
    int                   m_yScrollLinesPerPage;

    bool                  m_xScrollingEnabled;
    bool                  m_yScrollingEnabled;

    #if wxUSE_MOUSEWHEEL
    int m_wheelRotation;
    #endif

    wxScrollHelperEvtHandler *m_handler;

    DECLARE_NO_COPY_CLASS( wxScrollHelper )
};

#define WX_FORWARD_TO_SCROLL_HELPER()                                         \
  public:                                                                       \
  virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); }                     \
  virtual bool Layout() { return ScrollLayout(); }                          \
  virtual void DoSetVirtualSize(int x, int y)                               \
  { ScrollDoSetVirtualSize(x, y); }                                     \
  virtual wxSize GetBestVirtualSize() const                                 \
  { return ScrollGetBestVirtualSize(); }                                \
  protected:                                                                    \
  virtual wxSize GetWindowSizeForVirtualSize(const wxSize& size) const      \
  { return ScrollGetWindowSizeForVirtualSize(size); }

#if defined(__WXGTK20__) && !defined(__WXUNIVERSAL__)
#include "wx/gtk/scrolwin.h"
#elif defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
#include "wx/gtk1/scrolwin.h"
#else
typedef wxScrollHelper wxScrollHelperNative;
#endif

class wxScrolledWindow : public wxPanel,
  public wxScrollHelperNative {
  public:
    wxScrolledWindow() : wxScrollHelperNative( this ) { }
    wxScrolledWindow( wxWindow *parent,
                      wxWindowID winid = wxID_ANY,
                      const wxPoint& pos = wxDefaultPosition,
                      const wxSize& size = wxDefaultSize,
                      long style = wxScrolledWindowStyle,
                      const wxString& name = wxPanelNameStr )
      : wxScrollHelperNative( this ) {
      Create( parent, winid, pos, size, style, name );
    }

    virtual ~wxScrolledWindow();

    bool Create( wxWindow *parent,
                 wxWindowID winid,
                 const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize,
                 long style = wxScrolledWindowStyle,
                 const wxString& name = wxPanelNameStr );

    WX_FORWARD_TO_SCROLL_HELPER()

  protected:
    void OnPaint( wxPaintEvent& event );

  private:
    DECLARE_DYNAMIC_CLASS_NO_COPY( wxScrolledWindow )
    DECLARE_EVENT_TABLE()
};

#endif
